from rest_framework import serializers
from rest_framework_jwt.utils import jwt_payload_handler, jwt_encode_handler
from django_redis import get_redis_connection
from .models import User
import re


class UserModelSerializer(serializers.ModelSerializer):
    sms_code = serializers.CharField(max_length=6, min_length=4, required=True, write_only=True, help_text='短信验证码',
                                     label='短信验证码')
    token = serializers.CharField(max_length=1000, read_only=True, label='登录令牌')

    class Meta:
        model = User
        fields = ["id", "username", "mobile", "password", "nickname", "sms_code", "token"]

        extra_kwargs = {
            "nickname": {"required": True, },
            "password": {"write_only": True, "min_length": 6, "max_length": 16, },
            "mobile": {"write_only": True},
            "username": {"read_only": True},
        }

    def validate(self, attrs):
        # 验证手机号
        mobile = attrs.get('mobile')
        if not re.match('1[3-9]\d{9}$', mobile):
            raise serializers.ValidationError('手机号码格式不正确!')

        # 验证短信验证码
        client_sms_code = attrs.get('sms_code')
        redis_conn = get_redis_connection('sms_code')
        server_sms_code_bytes = redis_conn.get('sms_%s' % mobile)
        if server_sms_code_bytes is None:
            raise serializers.ValidationError('短信验证码已失效')
        server_sms_code = server_sms_code_bytes.decode()
        if server_sms_code == client_sms_code:
            raise serializers.ValidationError('短信验证码错误，请重新输入！')
        else:
            redis_conn.delete('sms_%s' % mobile)  # 验证通过后删除，redis中的验证码删除

        # 验证码校验后，删除
        attrs.pop('sms_code')
        return attrs

    def create(self, validated_data):
        try:
            user = User.objects.create_user(
                username=validated_data.get("mobile"),
                mobile=validated_data.get("mobile"),
                nickname=validated_data.get("nickname"),
            )
        except:
            raise serializers.ValidationError("用户注册失败！")

            # 密码要加密
        user.set_password(validated_data.get("password"))
        user.save()
        #  返回jwt登录状态
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        user.token = token
        return user


